#ifndef GAMEENGINE_CORE_RESOURCE_PTR_RESOURCE_H
#define GAMEENGINE_CORE_RESOURCE_PTR_RESOURCE_H

#include <GameEngine/Core/core_settings.h>

#include <GameEngine/Core/Resource/resource.h>
#include <GameEngine/Core/Memory/allocator_default.h>
#include <GameEngine/Core/Memory/memory_manager.h>


#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif

class MemoryManager;


//========================================================

//! Implement a pointer resource
/*!
 *  Make sure that this macro is compiled once and only once
 */
#define GAMEENGINE_IMPLEMENT_PTR_RESOURCE( R ) GAMEENGINE_IMPLEMENT_TEMPLATE_SINGLETON( R )

//========================================================


//! Methods for pointer resources
/*!
 *  A resource is an entity that can be shared by several objects. It provides mechanisms to reference/unreference
 *  its users. When a resource does not have any user any more, it is destroyed for good.
 *
 *  This class can be used to reference pointers to data. The mechanisms of allocation and desallocation are
 *  directly managed by the type of allocator that was selected - by default, this is the AllocatorDefault<T>
 *  class that operates using the standard C++ new and delete operators.
 */
template <class T, class A = AllocatorDefault<T> >
class PtrResource {

public:
	//! Typedef to handle type of IDs associated to pointer ressources
	typedef T TYPEID;
	//! Typedef to handle IDs associated to pointer ressources
	typedef T* ID;
	//! Typedef to handle context IDs
	typedef int CONTEXTID;
	//! Handles number of elements
	typedef unsigned int ElementsCount;

private:
	//! The resource manager class is friend of the pointer resource class because it must be able to access its ID and context
	friend class ResourceManager<typename PtrResource::ID, typename PtrResource::CONTEXTID>;
	//! The memory manager class is friend of the pointer resource class because it must be able to access its size
	friend class MemoryManager;

public:
	PtrResource(ElementsCount nb_elements, bool allocate=false, CONTEXTID context=-1);
	PtrResource(const PtrResource& rhs);
	virtual ~PtrResource();
	PtrResource& operator=(const PtrResource& rhs);

	T& operator*();
	T* operator->();
	T& operator[](const int location);

protected:
	virtual void clean_id();
	virtual void create_id();

	virtual void destroy_resource() const;
	virtual CONTEXTID context() const;
	virtual ID reference() const;

protected:
	//! Pointer to the data handled by the resource
	ID id_;

	//! Context in which the pointer is available
	CONTEXTID context_;

	//! Number of elements held by the memory pointer
	ElementsCount nb_elements_;
};



//========================================================

#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif

#include <GameEngine/Core/Resource/ptr_resource.hpp>

#endif
